package 剑指offer;

import common.TreeNode;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * @author zhangmin
 * @create 2021-11-16 10:37
 *
 * 6.搜索与回溯
 */
public class day6_321_322_323 {

    /**===========================================================================================================================
     * 剑指 Offer 32 - I. 从上到下打印二叉树
     * 从上到下打印出二叉树的每个节点，同一层的节点按照从左到右的顺序打印。
     * 层序遍历：队列
     * */
    public int[] levelOrder1(TreeNode root) {
        if(root==null) return new int[0];
        Queue<TreeNode> queue=new LinkedList<>();
        ArrayList<Integer> list=new ArrayList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            TreeNode cur = queue.poll();
            if (cur!=null){
                list.add(cur.val);
                queue.offer(cur.left);
                queue.offer(cur.right);
            }
        }
        int[] res=new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            res[i]=list.get(i);
        }
        return res;
    }
    /**===========================================================================================================================
     * 剑指 Offer 32 - II. 从上到下打印二叉树 II
     * 从上到下按层打印二叉树，同一层的节点按从左到右的顺序打印，每一层打印到一行。
     * 层序遍历，队列，对每一层计数，依次将一层的全部处理
     * */
    public List<List<Integer>> levelOrder2(TreeNode root) {
        if (root==null) return new LinkedList<>();
        Queue<TreeNode> queue=new LinkedList<>();
        List<List<Integer>> res=new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            int levelNum = queue.size();
            List<Integer> levelList=new LinkedList<>();
            for (int i = 0; i < levelNum; i++) {
                TreeNode node = queue.poll();
                levelList.add(node.val);
                if (node.left!=null){
                    queue.offer(node.left);
                }
                if (node.right!=null){
                    queue.offer(node.right);
                }
            }
            res.add(levelList);
        }
        return res;
    }


    /**===========================================================================================================================
     * 剑指 Offer 32 - III. 从上到下打印二叉树 III
     * 请实现一个函数按照之字形顺序打印二叉树，即第一行按照从左到右的顺序打印，第二层按照从右到左的顺序打印，第三行再按照从左到右的顺序打印，其他行以此类推。
     * 从0开始计数，偶数行从左到右，奇数行从右到左
     * */
    public List<List<Integer>> levelOrder(TreeNode root) {
        if (root==null) return new LinkedList<>();
        Queue<TreeNode> queue=new LinkedList<>();
        List<List<Integer>> res=new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()){
            int levelNum = queue.size();
            List<Integer> levelList=new LinkedList<>();
            for (int i = 0; i < levelNum; i++) {
                TreeNode node = queue.poll();
                levelList.add(node.val);
                if (node.left!=null){
                    queue.offer(node.left);
                }
                if (node.right!=null){
                    queue.offer(node.right);
                }
            }
            res.add(levelList);
        }
        for (int i = 0; i < res.size(); i++) {
            if (i%2==1){
                reverse(res.get(i));
            }
        }
        return res;
    }
    public void reverse(List<Integer> list){
        int i=0,j=list.size()-1;
        while (i<j){
            Integer temp = list.get(i);
            list.set(i,list.get(j));
            list.set(j,temp);
            i++;j--;
        }
    }

}
